﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Space
{
    public class Planet : PositionSized, ITarget
    {
        public string Type { get; set; }

        float population;
        public float Population
        {
            get { return population; }
            set
            {
                if (value <= 0)
                {
                    value = 0;
                    Player.RemovePlanet(this);
                    Player = Game.Services.GetService<IData>().NeutralPlayer;
                    Player.AddPlanet(this);
                }
                population = value;
            }
        }

        public float HP { get { return Population; } set { Population = value; } }
        public bool Alive { get { return true; } }

        public string Name { get; set; }
        
        float taxTimer;
        public float TaxInterval { get; set; }

        float productionProgress = 0;
        public Player Player { get; set; }

        public int ShipSupportNum { get; set; }
        public float Angle { get; set; }
        public float RotateSpeed { get; set; }

        //public float CircleSpeed { get; set; }
        public float Mass { get; set; }

        int value;
        public int Value { get { return value; } }

        Game game;
        public Game Game { get { return game; } }
        IBuildable buildingShip;

        public SolarSystem SolarSystem { get; set; }

        float tradeCounter;

        public float TaxRate { get; set; }

        public float Fertility { get; set; }
        public float FoodStore { get; set; }
        float foodEating = 2;
        float GrowthFood(int pop)
        {
            float baseFood = 100;
            for (int i = 0; i < pop; i++)
                baseFood *= 1.5f;
            return baseFood;
            //return (float)Math.Pow(1.4, pop) * 10;
        }
        public float UsableSpace { get; set; }

        public Model Model { get; set; }
        public Texture2D Texture { get; set; }
        public Planet(Game game)
        {
            this.game = game;
            TaxInterval = 10;
            TaxRate = 10;
            Fertility = 2.2f;
            UsableSpace = 20;

            value = 1000;
        }

        public void Update(float time)
        {
            Angle += RotateSpeed;

            //float recovery = ResistanceRecovery * 
            FoodStore -= Population * foodEating;
            FoodStore += Math.Min(UsableSpace, Population) * Fertility + 2;
            if(FoodStore < 0) {
                Population--;
                FoodStore=0;
            }
            if (FoodStore >= GrowthFood((int)Population))
            {
                Population++;
                FoodStore = 0;
            }
            //float recovery =;
            //Resistance = Math.Min(MaxResistance, Resistance + ResistanceRecovery * time);

            taxTimer += time;
            if (taxTimer >= TaxInterval)
            {
                taxTimer = 0;
                Player.Credit += (int)(Population * TaxRate);
            }

            if (!Player.Neutral)
            {
                float tradeInterval = 10 / Population;
                tradeCounter += time;
                if (tradeCounter >= tradeInterval)
                {
                    tradeCounter = 0;

                    IData data = Game.Services.GetService<IData>();
                    SolarSystem solar;
                    if (Game1.Rand.NextDouble() < 0.8)
                        solar = SolarSystem;
                    else solar = (from o in data.SolarSystems
                                  orderby Game1.Rand.Next()
                                  select o).First();

                    var v = from o in solar.Planets
                            where o != this && o.Player == Player
                            orderby Game1.Rand.Next()
                            select o;
                    Planet p = v.FirstOrDefault();

                    if (p != null)
                    {
                        float multiplier = 1;
                        solar.Buildings.FindAll(b => b.EffectName == "trade_multiply").ForEach(b => multiplier *= float.Parse(b.EffectArgument));
                        multiplier += 1;
                        TradeShip ts = new TradeShip(game)
                        {
                            Position = this.Position,
                            Destination = p,
                            Player = this.Player,
                        };
                        int tv = ts.TradeValue;
                        ts.TradeValue = (int)Math.Round(tv * multiplier);

                        data.AddShip(ts);
                    }
                }
            }

            //if (!Player.Neutral)
            //{
            //    if (Player.ShipCount < Player.ShipSupportCount)
            //    {
            //        productionProgress += time;
            //        if (productionProgress >= ProductionInterval)
            //        {
            //            productionProgress -= ProductionInterval;
            //            Ship ship = new FighterShip(game)
            //            {
            //                Fleet = this.Fleet,
            //                Player = this.Player,
            //                Position = this.Position
            //            };
            //            ship.CopyFrom(shipProduced);
            //            game.Services.GetService<IData>().AddShip(ship);
            //        }
            //    }
            //}

            float circleSpeed = 1 / (float)Math.Sqrt(Math.Pow((Position - SolarSystem.Position).Length(), 3) / SolarSystem.Mass);
            Position = Vector3.Transform(Position, Matrix.CreateTranslation(-SolarSystem.Position) * Matrix.CreateRotationY(circleSpeed * time) * Matrix.CreateTranslation(SolarSystem.Position));
        }

        public void Draw()
        {
            ICamera camera = game.Services.GetService<ICamera>();

            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    effect.CurrentTechnique = effect.Techniques["Technique1"];
                    effect.Parameters["World"].SetValue(Matrix.CreateRotationY(Angle) * Matrix.CreateTranslation(Position));
                    effect.Parameters["Projection"].SetValue(camera.Projection);
                    effect.Parameters["View"].SetValue(camera.View);
                    effect.Parameters["DiffuseColor"].SetValue(Color.White.ToVector3());
                    effect.Parameters["EmissiveColor"].SetValue(Color.Black.ToVector3());
                    effect.Parameters["Light1Direction"].SetValue(Vector3.Normalize(SolarSystem.Position - Position));
                    effect.Parameters["Texture"].SetValue(Texture);
                }
                mesh.Draw();
            }
        }

        internal void UpdateMainPlanet(float time)
        {
            if (buildingShip == null)
            {
                if (!Player.FlagShip.Built) buildingShip = Player.FlagShip;
                else buildingShip = Player.MainFleet.Find(s => !s.Built);

                productionProgress = 0;
            }
            if (buildingShip != null)
            {
                productionProgress += time;
                if (productionProgress >= buildingShip.BuildingTime)
                {
                    productionProgress -= buildingShip.BuildingTime;
                    buildingShip.Built = true;
                    buildingShip.Position = this.Position;
                    buildingShip = null;
                }
            }
        }

        public void TakeDamage(float damage)
        {
            HP -= damage;
            if (HP < 0) HP = 0;
        }
    }
}
